using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Windows;

#if !WINDOWS_PHONE && SILVERLIGHT
using System.Windows.Browser;
#endif

using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Hammock;
using Hammock.Authentication.OAuth;
using Hammock.Web;
using NetworkDetectionUtilities;

namespace SharpDropBoxClient
{
    public delegate void ThuziStyleRestClientAsyncCallback(ThuziStyleRestAsyncResult asyncResult);

    public interface IThuziStyleRestClientApiWithSignedOAuthUsingAppTokensAndUserTokens
    {
        string OAuthRequestUrl(string url, List<string> userParameters, string mode = "GET");
    }

    public class BaseDropBoxRestClient
    {
        internal const string kDboxHiddenFSPrefix = @"___dbox\";

        protected virtual string IsoStoreSettingsPrefix
        {
            get { return "DROPBOX"; }
        }

        protected const string ISOSTORAGE_USERTOKEN_SUFFIX = "TOKEN";
        protected const string ISOSTORAGE_USERSECRET_SUFFIX = "SECRET";
        protected string token = "";
        protected string userSecret = "";
        protected string apiKey;
        protected string apiSecret;

        public virtual string Token
        {
            get
            {
                if (String.IsNullOrEmpty(token))
                    if (System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings.Contains(IsoStoreSettingsPrefix + ISOSTORAGE_USERTOKEN_SUFFIX))
                        token = (string)System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings[IsoStoreSettingsPrefix + ISOSTORAGE_USERTOKEN_SUFFIX];
                return token;
            }
            set
            {
                token = value;
                System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings[IsoStoreSettingsPrefix + ISOSTORAGE_USERTOKEN_SUFFIX] = token;
            }
        }

        public virtual string UserSecret
        {
            get
            {
                if (String.IsNullOrEmpty(userSecret))
                    if (System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings.Contains(IsoStoreSettingsPrefix + ISOSTORAGE_USERSECRET_SUFFIX))
                        userSecret = (string)System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings[IsoStoreSettingsPrefix + ISOSTORAGE_USERSECRET_SUFFIX];
                return userSecret;
            }
            set
            {
                userSecret = value;
                System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings[IsoStoreSettingsPrefix + ISOSTORAGE_USERSECRET_SUFFIX] = userSecret;
            }
        }

        public virtual bool MimicDropBoxFileSystemLocally { get; set; }

        public virtual bool HaveToken
        {
            get
            {
                return !String.IsNullOrEmpty(Token);
            }
        }

        public virtual bool HaveUserSecret
        {
            get
            {
                return !String.IsNullOrEmpty(UserSecret);
            }
        }

        public BaseDropBoxRestClient()
        {
        }

        protected IDbCache db;
        protected const string APIBASEURL = "https://api.dropbox.com/0";
        protected const string APISUBDOMAINBASEURL = "https://api-content.dropbox.com/0";
        protected INetworkDetector netDetector;
        protected const string TOKENCOMMAND = @"/token";
        protected const string ACCOUNTINFOCOMMAND = @"/account/info";
        protected const string ACCOUNTCOMMAND = @"/account"; // Not implemented (POST)
        protected const string FILESCOMMAND = @"/files"; // Not FULLY implemented
        protected const string LISTCOMMAND = @"/metadata";
        protected const string THUMBNAILSCOMMAND = @"/thumbnails"; // Not implemented (GET)
        protected const string COPYCOMMAND = @"/fileops/copy";
        protected const string MAKEDIRCOMMAND = @"/fileops/create_folder";
        protected const string DELETECOMMAND = @"/fileops/delete";
        protected const string MOVECOMMAND = @"/fileops/move";
    }

    public class ThuziStyleRestClientApiWithSignedOAuthUsingAppTokensAndUserTokens : BaseDropBoxRestClient, IThuziStyleRestClientApiWithSignedOAuthUsingAppTokensAndUserTokens
    {
        protected void DBXxAuth(string baseUrl, string path, string email, string password, ThuziStyleRestClientAsyncCallback callback)
        {
            //var credentials = new OAuthCredentials
            //            {
            //                Type = OAuthType.ClientAuthentication,
            //                ParameterHandling = OAuthParameterHandling.HttpAuthorizationHeader,
            //                SignatureMethod = OAuthSignatureMethod.HmacSha1,
            //                SignatureTreatment = OAuthSignatureTreatment.Escaped,
            //                ConsumerKey = apiKey,
            //                ConsumerSecret = apiSecret,
            //                ClientUsername = email,
            //                ClientPassword = password
            //            };
            var client = new RestClient
            {
                Authority = baseUrl
            };

            var request = new RestRequest
            {
                Path = path,
                Method = WebMethod.Get,
            };
            request.AddParameter("oauth_consumer_key", apiKey);
            request.AddParameter("email", email);
            request.AddParameter("password", password);

            client.BeginRequest(request, (req, resp, state) =>
            {
                ResponseCallback(req, resp, state, callback);
            });
        }

        private OAuthCredentials GetCredentials()
        {
            var credentials = new OAuthCredentials
                                    {
                                        Type = OAuthType.AccessToken,
                                        ParameterHandling = OAuthParameterHandling.UrlOrPostParameters,
                                        SignatureMethod = OAuthSignatureMethod.HmacSha1,
                                        SignatureTreatment = OAuthSignatureTreatment.Escaped,
                                        ConsumerKey = apiKey,
                                        ConsumerSecret = apiSecret,
                                        Token = this.Token,
                                        TokenSecret = this.UserSecret
                                    };

            return credentials;
            //return OAuthCredentials.ForAccessToken(apiKey, apiSecret, Token, UserSecret);
        }

        protected void DoAsyncRetrieve(string baseUrl, List<string> parameters, string httpMethod, ThuziStyleRestClientAsyncCallback callback)
        {
            baseUrl = baseUrl.Replace("+", "%20");
            OAuthCredentials credentials = GetCredentials();

            var client = new RestClient
            {
                Authority = baseUrl,
                Credentials = credentials,
            };

            var request = new RestRequest
            {
                Method = (httpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase) ? WebMethod.Post : WebMethod.Get),
            };
            applyParams(request, parameters);
            //ApplyDBOXOAuthToRequest(baseUrl, parameters, httpMethod, request);

            client.BeginRequest(request, (req, resp, state) =>
            {
                ResponseCallback(req, resp, state, callback);
            });
        }

        private void applyParams(RestRequest request, List<string> parameters)
        {
            request.AddParameter("oauth_callback", "oob");
            foreach (var parm in parameters)
            {
                var keyValue = parm.Split('=');
                if (keyValue.Length == 2)
                {
                    request.AddParameter(keyValue[0], keyValue[1]);
                }
            }
        }

        protected void DoAsyncRetrieve(string baseUrl, string path, List<string> parameters, string httpMethod, ThuziStyleRestClientAsyncCallback callback)
        {
            baseUrl = baseUrl.Replace("+", "%20");
            path = path.Replace(@"\", @"/").Replace("+", "%20");
            var credentials = GetCredentials();

            var client = new RestClient
            {
                Authority = baseUrl,
                Credentials = credentials,
                CacheOptions = new Hammock.Caching.CacheOptions { Mode = Hammock.Caching.CacheMode.AbsoluteExpiration, Duration = new TimeSpan(0, 0, 10) },
            };

            var request = new RestRequest
            {
                Path = path,
                Method = (httpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase) ? WebMethod.Post : WebMethod.Get),
            };
            applyParams(request, parameters);

            //ApplyDBOXOAuthToRequest(baseUrl, parameters, httpMethod, request);
            client.BeginRequest(request, (req, resp, state) =>
            {
                ResponseCallback(req, resp, state, callback);
            });
        }

        //protected void DoAsyncRetrieve(string baseUrl, string path, List<string> parameters, string httpMethod, ThuziStyleRestClientAsyncCallback callback)
        //{
        //    baseUrl = baseUrl.Replace("+", "%20");
        //    path = path.Replace(@"\", @"/").Replace("+", "%20");

        //    var client = new RestClient
        //    {
        //        Authority = baseUrl,
        //        CacheOptions = new Hammock.Caching.CacheOptions { Mode = Hammock.Caching.CacheMode.AbsoluteExpiration, Duration = new TimeSpan(0, 0, 10) }
        //    };

        //    var request = new RestRequest
        //    {
        //        Path = path,
        //        Method = (httpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase) ? WebMethod.Post : WebMethod.Get),
        //    };

        //    ApplyDBOXOAuthToRequest(baseUrl, parameters, httpMethod, request);

        //    client.BeginRequest(request, (req, resp, state) =>
        //    {
        //        ResponseCallback(req, resp, state, callback);
        //    });
        //}

        protected void ResponseCallback(RestRequest request, RestResponse response, object state, ThuziStyleRestClientAsyncCallback callback)
        {
            object result = null;
            var content = "";
            DropBoxApiException exception = null;
            var httpStatusCode = HttpStatusCode.NoContent;
            try
            {
                if (response.InnerException != null)
                {
                    exception = new DropBoxApiException("Error retrieving response", response.InnerException);
                }
                else
                {
                    //var request = (HttpWebRequest)asyncResult.AsyncState;
                    //var response = (HttpWebResponse)request.EndGetResponse(asyncResult);
                    httpStatusCode = response.StatusCode;
                    result = JsonSerializer.DeserializeObject(response.Content);
                    content = response.Content;
                }
            }
            catch (DropBoxApiException ex1)
            {
                // Rest API Errors
                exception = ex1;
            }
            catch (WebException ex)
            {
                // Graph API Errors or general web exceptions
                exception = ExceptionFactory.GetGraphException(ex);
                if (exception == null)
                {
                    exception = new DropBoxApiException("Error retrieving response", ex);
                }
            }
            finally
            {
                // Check to make sure there hasn't been an exception.
                // If there has, we want to pass null to the callback.
                object data = null;
                if (exception == null)
                    data = result;
                callback(new ThuziStyleRestAsyncResult(data, content, httpStatusCode, exception));
            }
        }

        //protected void ResponseCallback(IAsyncResult asyncResult, ThuziStyleRestClientAsyncCallback callback, object state)
        //{
        //    object result = null;
        //    DropBoxApiException exception = null;
        //    var content = "";
        //    var httpStatusCode = HttpStatusCode.NoContent;
        //    try
        //    {
        //        var request = (HttpWebRequest)asyncResult.AsyncState;
        //        var response = (HttpWebResponse)request.EndGetResponse(asyncResult);
        //        httpStatusCode = response.StatusCode;
        //        using (Stream responseStream = response.GetResponseStream())
        //        {
        //            result = JsonSerializer.DeserializeObject(responseStream);
        //            content = JsonSerializer.SerializeObject(result);
        //        }
        //    }
        //    catch (DropBoxApiException ex1)
        //    {
        //        // Rest API Errors
        //        exception = ex1;
        //    }
        //    catch (WebException ex)
        //    {
        //        // Graph API Errors or general web exceptions
        //        exception = ExceptionFactory.GetGraphException(ex);
        //        if (exception == null)
        //        {
        //            exception = new DropBoxApiException("Error retrieving response", ex);
        //        }
        //    }
        //    finally
        //    {
        //        // Check to make sure there hasn't been an exception.
        //        // If there has, we want to pass null to the callback.
        //        object data = null;
        //        if (exception == null)
        //            data = result;
        //        callback(new ThuziStyleRestAsyncResult(data, content, httpStatusCode, exception));
        //    }
        //}

        private class StatePlusParam
        {
            public HttpWebRequest wr { get; set; }

            public object parm1 { get; set; }
        }

        protected void DoAsyncRetrieveURI(string baseUrl, string path, List<string> parameters, string httpMethod, ThuziStyleRestClientAsyncCallback callback)
        {
            try
            {
                baseUrl = baseUrl.Replace("+", "%20");
                path = path.Replace(@"\", @"/").Replace("+", "%20");
                //var credentials = GetCredentials();

                //var client = new RestClient
                //{
                //    Authority = baseUrl,
                //    CacheOptions = new Hammock.Caching.CacheOptions { Mode = Hammock.Caching.CacheMode.AbsoluteExpiration, Duration = new TimeSpan(0, 0, 10) }
                //};

                //var request = new RestRequest
                //{
                //    Path = path,
                //    Method = (httpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase) ? WebMethod.Post : WebMethod.Get),
                //    Credentials = credentials
                //};
                //applyParams(request, parameters);

                //var qi = new OAuthWebQueryInfo();
                //var q2 = credentials.GetQueryFor(baseUrl, request, (IWebQueryInfo)qi, (httpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase) ? WebMethod.Post : WebMethod.Get));

                var concatPath = (baseUrl + ((baseUrl.EndsWith("/")) ? "" : "/") + ((!path.StartsWith("/")) ? path : path.Substring(1)));
                var uri = OAuthRequestUrl(concatPath, parameters, httpMethod);
                //var q = client.GetQueryFor(request, new Uri(baseUrl));
                //var uri = new StringBuilder(baseUrl + path + "?");
                //bool gotCallback = false;
                //for (int i = 0; i < q.Parameters.Count; i++)
                //{
                //    if (i > 0)
                //        uri.Append("&");
                //    if (q.Parameters[i].Name == "oauth_callback")
                //        gotCallback = true;
                //    uri.AppendFormat("{0}={1}", q.Parameters[i].Name, q.Parameters[i].Value);
                //}
                //if (!gotCallback)
                //    uri.AppendFormat("{0}{1}={2}", (q.Parameters.Count == 0 ? "?" : "&"), "oauth_callback", "oob");

                callback(new ThuziStyleRestAsyncResult(uri.ToString(), uri.ToString(), HttpStatusCode.NoContent, null));
            }
            catch (Exception ex)
            {
                callback(new ThuziStyleRestAsyncResult(null, "", HttpStatusCode.NoContent, new DropBoxApiException("Cannot generate URI", ex)));
            }
        }
        protected ThuziStyleRestAsyncResult DoRetrieveURI(string baseUrl, string path, List<string> parameters, string httpMethod)
        {
            try
            {
                baseUrl = baseUrl.Replace("+", "%20");
                path = path.Replace(@"\", @"/").Replace("+", "%20");

                var concatPath = (baseUrl + ((baseUrl.EndsWith("/")) ? "" : "/") + ((!path.StartsWith("/")) ? path : path.Substring(1)));
                var uri = OAuthRequestUrl(concatPath, parameters, httpMethod);
                return new ThuziStyleRestAsyncResult(uri.ToString(), uri.ToString(), HttpStatusCode.NoContent, null);
            }
            catch (Exception ex)
            {
                return new ThuziStyleRestAsyncResult(null, "", HttpStatusCode.NoContent, new DropBoxApiException("Cannot generate URI", ex));
            }
        }

        protected void DoAsyncRetrieveToFile(string baseUrl, string path, List<string> parameters, string httpMethod, string IsoFilePath, ThuziStyleRestClientAsyncCallback callback)
        {
            baseUrl = baseUrl.Replace("+", "%20");
            path = path.Replace(@"\", @"/").Replace("+", "%20");
            var credentials = GetCredentials();

            var client = new RestClient
            {
                Authority = baseUrl,
                CacheOptions = new Hammock.Caching.CacheOptions { Mode = Hammock.Caching.CacheMode.AbsoluteExpiration, Duration = new TimeSpan(0, 0, 10) }
            };

            var request = new RestRequest
            {
                Path = path,
                Method = (httpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase) ? WebMethod.Post : WebMethod.Get),
                Credentials = credentials
            };
            applyParams(request, parameters);

            client.BeginRequest(request, (req, resp, isoFilePath) =>
            {
                ResponseCallbackResultsToIsoFile(req, resp, isoFilePath, callback);
            }, IsoFilePath);
        }

        protected void DoAsyncRetrieveStream(string baseUrl, string path, List<string> parameters, string httpMethod, ThuziStyleRestClientAsyncCallback callback)
        {
            baseUrl = baseUrl.Replace("+", "%20");
            path = path.Replace(@"\", @"/").Replace("+", "%20");

            var credentials = GetCredentials();
            var client = new RestClient
            {
                Authority = baseUrl,
                CacheOptions = new Hammock.Caching.CacheOptions { Mode = Hammock.Caching.CacheMode.AbsoluteExpiration, Duration = new TimeSpan(0, 0, 10) }
            };

            var request = new RestRequest
            {
                Path = path,
                Method = (httpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase) ? WebMethod.Post : WebMethod.Get),
                Credentials = credentials,
            };
            applyParams(request, parameters);

            client.BeginRequest(request, (req, resp, state) =>
            {
                ResponseCallbackResultsToIsoFile(req, resp, state, callback);
            });
        }

        private void ResponseCallbackResultsToIsoFile(RestRequest request, RestResponse response, object state, ThuziStyleRestClientAsyncCallback callback)
        {
            var isoFilePath = (string)(state ?? "");
            object result = "";
            var content = "";
            DropBoxApiException exception = null;
            var httpStatusCode = HttpStatusCode.NoContent;
            try
            {
                httpStatusCode = response.StatusCode;
                using (Stream responseStream = response.ContentStream)
                {
                    if (!String.IsNullOrEmpty(isoFilePath))
                    {
                        using (Stream createdFile = createIsoPathAndFile(isoFilePath))
                        {
                            try
                            {
                                if (createdFile == null)
                                {
                                    throw new IOException("Can not create cached file");
                                }
                                writeResponseToStream(responseStream, createdFile);
                            }
                            finally
                            {
                                createdFile.Close();
                            }
                        };
                        result = ((MimicDropBoxFileSystemLocally ? "" : kDboxHiddenFSPrefix) + isoFilePath).Replace(@"/", @"\").Replace(@"\\", @"\");

                        content = (string)result;
                    }
                    else
                    {
                        byte[] buffer = null;
                        using (Stream streamReader = new MemoryStream())
                        {
                            writeResponseToStream(responseStream, streamReader);
                            buffer = ((MemoryStream)streamReader).GetBuffer();
                        };
                        result = new MemoryStream(buffer);
                    }
                }
            }

            catch (DropBoxApiException ex1)
            {
                // Rest API Errors
                exception = ex1;
            }
            catch (WebException ex)
            {
                // Graph API Errors or general web exceptions
                exception = ExceptionFactory.GetGraphException(ex);
                if (exception == null)
                {
                    exception = new DropBoxApiException("Error retrieving response", ex);
                }
            }

            finally
            {
                // Check to make sure there hasn't been an exception.
                // If there has, we want to pass null to the callback.
                object data = null;
                if (exception == null)
                    data = result;
                callback(new ThuziStyleRestAsyncResult(data, content, httpStatusCode, exception));
            }
        }

        protected void PostFile(string baseUrl, string path, Stream file, string fileName, ThuziStyleRestClientAsyncCallback callback)
        {
            baseUrl = baseUrl.Replace("+", "%20");
            path = path.Replace(@"\", @"/").Replace("+", "%20");
            var credentials = GetCredentials();
            credentials.Type = OAuthType.ProtectedResource;
            var client = new RestClient
            {
                Authority = baseUrl,
                CacheOptions = new Hammock.Caching.CacheOptions { Mode = Hammock.Caching.CacheMode.AbsoluteExpiration, Duration = new TimeSpan(0, 0, 10) }
            };

            var request = new RestRequest
            {
                Path = path,
                Method = WebMethod.Post,
                Credentials = credentials,
            };
            request.AddFile("file", fileName, file);
            request.AddParameter("file", fileName);

            client.BeginRequest(request, (req, resp, state) =>
            {
                try
                {
                    callback(new ThuziStyleRestAsyncResult(null, "", resp.StatusCode, null));
                }
                catch (Exception ex3)
                {
                    callback(new ThuziStyleRestAsyncResult(null, "", HttpStatusCode.BadRequest, new DropBoxApiException("Error While processing response", ex3)));
                }
            });
        }

        private static void writeResponseToStream(Stream responseStream, Stream createdFile)
        {
            var buffer = new byte[1048576]; // 1mb chunks
            var byteCount = responseStream.Read(buffer, 0, 1048576);
            while (byteCount > 0)
            {
                createdFile.Write(buffer, 0, byteCount);

                byteCount = responseStream.Read(buffer, 0, 1048576);
            }
        }

        private Stream createIsoPathAndFile(string filePath)
        {
            try
            {
                var newPath = ((!MimicDropBoxFileSystemLocally ? kDboxHiddenFSPrefix : "") + filePath).Replace(@"/", @"\").Replace(@"\\", @"\");

                var pathPieces = newPath.Split('\\');
                var existingPath = "";
                for (int i = 0; i < pathPieces.Length - 1; i++)
                {
                    existingPath += (existingPath.Length > 0 ? @"\" : "") + pathPieces[i];
                    var dir = new PSDirectoryInfo(existingPath);
                    if (!dir.Exists)
                    {
                        dir.Create();
                    }
                }
                var newFile = new PSFileInfo(newPath);
                if (newFile.Exists)
                {
                    // We overwrite
                    newFile.Delete();
                }
                return newFile.Create();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #region OAuthStuff

        /// <summary>
        /// Generates a new nonce, must be unique for each OAuth request
        /// </summary>
        /// <returns>nonce as string</returns>
        public static string nonce()
        {
            return new Random().Next(123400, 9999999).ToString();
        }

        public string OAuthRequestUrl(string url, List<string> userParameters, string mode = "GET")
        {
            url = url.Replace("+", "%20");

            List<string> Parameters = userParameters;
            Parameters.Add("oauth_consumer_key=" + HttpUtility.UrlEncode(apiKey));
            Parameters.Add("oauth_nonce=" + HttpUtility.UrlEncode(nonce()));
            Parameters.Add("oauth_signature_method=HMAC-SHA1");
            Parameters.Add("oauth_version=1.0");
            Parameters.Add("oauth_callback=oob");
            Parameters.Add("oauth_timestamp=" + HttpUtility.UrlEncode(timestamp()));
            if (HaveToken)
                Parameters.Add("oauth_token=" + Token);
            Parameters.Sort();
            string parametersStr = string.Join("&", Parameters.ToArray());
            string baseStr = mode + "&" + HttpUtility.UrlEncode(url).Replace("%2f", "%2F").Replace("%3a", "%3A").Replace("%3d", "%3D") + "&" + HttpUtility.UrlEncode(parametersStr).Replace("%2f", "%2F").Replace("%3a", "%3A").Replace("%3d", "%3D");
            /* create the crypto class we use to generate a signature for the request */
            byte[] key = Encoding.UTF8.GetBytes(apiSecret);
            if (HaveUserSecret)
                key = Encoding.UTF8.GetBytes(apiSecret + "&" + userSecret);
            HMACSHA1 sha1 = new HMACSHA1(key);

            byte[] baseStringBytes = Encoding.UTF8.GetBytes(baseStr);
            byte[] baseStringHash = sha1.ComputeHash(baseStringBytes);
            String base64StringHash = Convert.ToBase64String(baseStringHash);
            String encBase64StringHash = HttpUtility.UrlEncode(base64StringHash);
            Parameters.Add("oauth_signature=" + encBase64StringHash);
            //Parameters.Sort();
            return (url + "?" + string.Join("&", Parameters.ToArray()));
        }

        /// <summary>
        /// Gets a timestamp in the format required for OAuth
        /// </summary>
        /// <returns>timestamp as string</returns>
        public static string timestamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        private void ApplyDBOXOAuthToRequest(string baseUrl, List<string> parameters, string httpMethod, RestRequest request)
        {
            //            var url = baseUrl + request.Path;
            //#if DEBUG
            //            var testUrl = (new StringBuilder(url)).ToString();
            //            var testParams = parameters.ToArray().ToList();
            //            // The following is a call to the original function I borrowed that does this
            //            var testResult = OAuthRequestUrl(testUrl, testParams, httpMethod.ToUpper());
            //            // Now I can set the Nonce and timestamp mnually in debug mode and then check the resulting URI
            //#endif
            //            var uriParms = new Dictionary<string, string>();

            //            parameters.ToList().ForEach(item =>
            //            {
            //                // Old Function too list of string in the form of "qsVar=value" (and that is what is being passed in
            //                // So first of all we are adding these value to our dictionary that we'll use at the end to populate
            //                // the RestRequest with
            //                var keyValue = item.Split('=');
            //                var parmKey = "";
            //                var parmValue = "";
            //                if (keyValue.Length >= 1)
            //                {
            //                    parmKey = keyValue[0];
            //                }
            //                if (keyValue.Length == 2)
            //                {
            //                    parmValue = keyValue[1];
            //                }
            //                else if (keyValue.Length > 2)
            //                {
            //                    parmValue = string.Join("=", keyValue.Skip(1).ToArray());
            //                }
            //                if (!string.IsNullOrEmpty(parmKey))
            //                    uriParms.Add(parmKey, parmValue);
            //            });

            //            uriParms.Add("oauth_consumer_key", HttpUtility.UrlEncode(apiKey));
            //            if (!uriParms.ContainsKey("oauth_nonce")) // placed here for testing (I can override these during debug so I can test that hash vals are the same)
            //                uriParms.Add("oauth_nonce", HttpUtility.UrlEncode(nonce())); // Nonce is a random number between 12400  and 9999999
            //            uriParms.Add("oauth_signature_method", "HMAC-SHA1");
            //            uriParms.Add("oauth_version", "1.0");
            //            uriParms.Add("oauth_callback", "oob");
            //            if (!uriParms.ContainsKey("oauth_timestamp")) // placed here for testing (I can override these during debug so I can test that the hash vals are the same)
            //                uriParms.Add("oauth_timestamp", HttpUtility.UrlEncode(timestamp()));

            //            if (HaveToken)
            //                uriParms.Add("oauth_token", Token); // Token is the user token we get back from auth

            //            parameters.Clear();  // VERY INEFICIENT I KNOW (we are clearing our original passed in structure and are re filling it with data
            //            uriParms.Keys.ToList().ForEach(uriParmkey =>
            //            {
            //                parameters.Add(string.Format("{0}={1}", uriParmkey, uriParms[uriParmkey]));
            //            });
            //            parameters.Sort(); // we sort the data (as this is important)
            //            string parametersStr = string.Join("&", parameters.ToArray());
            //            string baseStr = httpMethod.ToUpper() + "&" +
            //                             HttpUtility.UrlEncode(url).Replace("%2f", "%2F")
            //                             .Replace("%3a", "%3A")
            //                             .Replace("%3d", "%3D") +
            //                             "&" +
            //                             HttpUtility.UrlEncode(parametersStr)
            //                             .Replace("%2f", "%2F")
            //                             .Replace("%3a", "%3A")
            //                             .Replace("%3d", "%3D");
            //            /* create the crypto class we use to generate a signature for the request */
            //            byte[] key = Encoding.UTF8.GetBytes(apiSecret);
            //            if (HaveUserSecret)
            //                key = Encoding.UTF8.GetBytes(apiSecret + "&" + userSecret);
            //            HMACSHA1 sha1 = new HMACSHA1(key);

            //            byte[] baseStringBytes = Encoding.UTF8.GetBytes(baseStr);
            //            byte[] baseStringHash = sha1.ComputeHash(baseStringBytes);
            //            String base64StringHash = Convert.ToBase64String(baseStringHash);
            //            String encBase64StringHash = HttpUtility.UrlEncode(base64StringHash);
            //            uriParms.Add("oauth_signature", encBase64StringHash);

            //            // Finally we add the qs vars to the RestClient sorted alphabetically (including the "=" and the value)
            //            (from item in uriParms
            //             orderby item.Key + "=" + item.Value
            //             select item).ToList().ForEach(parm =>
            //             {
            //                 if (!(parm.Key == "file" && httpMethod.Equals("POST", StringComparison.InvariantCultureIgnoreCase)))
            //                 {
            //                     request.AddParameter(parm.Key, parm.Value);
            //                 }
            //             });
        }

        #endregion OAuthStuff
    }
}